package main

import (
	"fmt"
	"unsafe"
)

type Book struct {
	Title  string
	Author string
	Page   uint
	Tag    []string
}

// 根据结构体的内存地址, 计算出Tag的内存地址, 并访问
func main() {
	b := &Book{Tag: []string{"abc", "def", "hjk"}}
	//结构体指针取属性值的时候直接使用b.Tag，而不是*b.Tag
	//Offsetof返回结构体成员在内存中的位置离结构体起始处的字节数，所传参数必须是 -结构体的成员
	fmt.Printf("b：%p\n", b)                  //0xc000024080
	fmt.Printf("Title 的内存地址：%p\n", &b.Title) //0xc000024080
	pTitle := (*[]string)(unsafe.Pointer(uintptr(unsafe.Pointer(b)) + unsafe.Offsetof(b.Title)))
	fmt.Printf("title 的内存地址：%p\n", pTitle)     //0xc000024080
	fmt.Printf("title 的值：%v\n", *pTitle)       //[]
	fmt.Printf("Tag 的内存地址：%p\n", &b.Tag)       //0xc0000240a8
	fmt.Printf("Tag 的值：%p\n", *&b.Tag)         //[abc def hjk]
	fmt.Printf("Tag[0] 的内存地址：%p\n", &b.Tag[0]) //0xc00007e3c0 为什么不等于&b.Tag?
	fmt.Printf("Tag[0] 的值是：%v\n", *&b.Tag[0])  //abc
	fmt.Printf("Tag[1] 的内存地址：%p\n", &b.Tag[1]) //0xc00007e3d0
	fmt.Printf("Tag[1] 的值是：%v\n", *&b.Tag[1])  //def
	fmt.Printf("Tag[2] 的内存地址：%p\n", &b.Tag[2]) //0xc00007e3e0
	fmt.Printf("Tag[2] 的值是：%v\n", *&b.Tag[2])  //hjk
	//利用unsafe.Pointer()求出Tag[i]的地址和值
	fmt.Printf("通过内存地址访问Tag[0]Tag[1]\n")
	pTag := (*[]string)(unsafe.Pointer(uintptr(unsafe.Pointer(b)) + unsafe.Offsetof(b.Tag))) //为什么不等于pTag0???
	fmt.Printf("Tag 的内存地址：%p\n", pTag)                                                       //0xc0000240a8
	fmt.Printf("Tag 的值是：%v\n", *pTag)                                                        //[abc def hjk]
	pTag0 := (*string)(unsafe.Pointer(uintptr(unsafe.Pointer(&b.Tag[0]))))
	fmt.Printf("Tag[0] 的内存地址：%p\n", pTag0)   //0xc00007e3c0
	fmt.Printf("Tag[0] 的值是：   %v\n", *pTag0) //abc
	//pTag1 := (*string)(unsafe.Pointer(uintptr(unsafe.Pointer(b)) + unsafe.Offsetof(b.Tag) + unsafe.Sizeof(b.Tag[0])))
	//上面访问不了值，地址跟下面不一样哪个对？
	pTag1 := (*string)(unsafe.Pointer(uintptr(unsafe.Pointer(&b.Tag[0])) + unsafe.Sizeof(b.Tag[0])))

	fmt.Printf("Tag[1] 的内存地址：%p\n", pTag1)   //0xc00007e3d0
	fmt.Printf("Tag[1] 的值是：   %v\n", *pTag1) //def
	//pTag2 := (*string)(unsafe.Pointer(uintptr(unsafe.Pointer(b)) + unsafe.Offsetof(b.Tag) + unsafe.Sizeof(b.Tag[0])+unsafe.Sizeof(b.Tag[1])))
	//上面访问不了值，地址跟下面不一样哪个对？
	pTag2 := (*string)(unsafe.Pointer(uintptr(unsafe.Pointer(&b.Tag[0])) + unsafe.Sizeof(b.Tag[0]) + unsafe.Sizeof(b.Tag[1])))
	fmt.Printf("Tag[2] 的内存地址：%p\n", pTag2)   //0xc00007e3e0
	fmt.Printf("Tag[2] 的值是：   %v\n", *pTag2) //hjk

	a := [3]int64{1, 2, 3}
	fmt.Printf("%p\n", &a)     //0xc00000a1b0
	fmt.Printf("%p\n", &a[0])  //0xc00000a1b0
	fmt.Printf("%v\n", *&a)    //[1 2 3]
	fmt.Printf("%v\n", *&a[0]) // 1

}
